package com.beiding.hotcode;

import java.io.File;
import java.util.HashMap;
import java.util.Map;

/*
    自己或者内部有任何一个发生改变都视为改变

    监控的文件一定要尽可能少,不然扫描会非常耗时

 */
public class FileMonitor {

    private File file;

    public FileMonitor(File file) {
        this.file = file;
    }

    private boolean change = false;

    private long lastCheck = 0;

    private Map<File, FileMonitor> subFileMap;

    public boolean checkChange() {
        if (change) {
            return true;
        }

        long lastModified = file.lastModified();

        if (lastModified != lastCheck) {
            change = true;
            lastCheck = lastModified;
        }

        if (!file.exists()) {
            if (subFileMap != null) {
                change = true;
                subFileMap = null;
            }
            lastCheck = 0;
        } else if (file.isDirectory()) {
            File[] files = file.listFiles();
            if (files == null) {
                if (subFileMap != null) {
                    change = true;
                    subFileMap = null;
                }
            } else {
                if (subFileMap == null) {
                    subFileMap = new HashMap<>();
                    change = true;
                    for (File f : files) {
                        FileMonitor monitor = new FileMonitor(f);
                        monitor.checkChange();
                        subFileMap.put(f, monitor);
                    }
                } else {
                    Map<File, FileMonitor> nm = new HashMap<>();
                    for (File f : files) {
                        FileMonitor monitor = subFileMap.remove(f);
                        if (monitor == null) {
                            monitor = new FileMonitor(f);
                            change = true;
                            monitor.checkChange();
                            nm.put(f, monitor);
                        } else {
                            if (monitor.checkChange()) {
                                change = true;
                            }
                            nm.put(f, monitor);
                        }
                    }
                    if (subFileMap.size() > 0) {
                        change = true;
                    }
                    subFileMap = nm;
                }
            }
        } else if (file.isFile()) {
            if (subFileMap != null) {
                change = true;
                subFileMap = null;
            }
        }

        return change;
    }

    public void resetChange() {
        change = false;
        if (subFileMap != null) {
            for (FileMonitor fileMonitor : subFileMap.values()) {
                fileMonitor.resetChange();
            }
        }
    }

    public File getFile() {
        return file;
    }


    @Override
    public int hashCode() {
        return file.hashCode();
    }

    @Override
    public boolean equals(Object obj) {

        //文件相同即相同
        if (obj instanceof FileMonitor) {
            return this.file.equals(((FileMonitor) obj).getFile());
        }

        return false;
    }
}
